package eabnp.eflow.server.impl.hb.flowengine;

import eabnp.basic.result.GResult;
import eabnp.basic.result.IResult;
import eabnp.basic.result.SGResult;
import eabnp.basic.result.SimpleResult;
import eabnp.basic.sequence.ComparatorBySeqNum;
import eabnp.basic.util.DateTimeUtil;
import eabnp.basic.util.MiscUtil;
import eabnp.basic.util.StringUtil;
import eabnp.basic.util.array.ArrayUtil;
import eabnp.eflow.EFlow;
import eabnp.eflow.EFlowConst;
import eabnp.eflow.info.ctrlinfo.processctrl.ConfirmCtrl;
import eabnp.eflow.info.ctrlinfo.processctrl.SelSendCtrl;
import eabnp.eflow.info.ctrlinfo.processctrl.SelSendListCtrl;
import eabnp.eflow.info.ctrlinfo.processctrl.actresult.ActResultListCtrl;
import eabnp.eflow.info.ctrlinfo.sysctrl.UserCtrlInfo;
import eabnp.eflow.info.ctrlinfo.sysctrl.basicinfo.ActInfo;
import eabnp.eflow.info.ctrlinfo.sysctrl.basicinfo.AppInfo;
import eabnp.eflow.info.ctrlinfo.sysctrl.basicinfo.UserInfo;
import eabnp.eflow.misc.OrgOUUserLevel;
import eabnp.eflow.misc.TaskState;
import eabnp.eflow.misc.acttype.ActType;
import eabnp.eflow.misc.formula.FormulaArray;
import eabnp.eflow.misc.userandparent.UserResult;
import eabnp.eflow.server.apicall.EFlowApiCall;
import eabnp.eflow.server.impl.flowxml.element.XAct;
import eabnp.eflow.server.impl.flowxml.element.XFlow;
import eabnp.eflow.server.impl.flowxml.element.XReceiverScope;
import eabnp.eflow.server.impl.flowxml.element.XSend;
import eabnp.eflow.server.impl.flowxml.element.XSplit;
import eabnp.eflow.server.impl.flowxml.element.XStep;
import eabnp.eflow.server.impl.flowxml.element.XUserScope;
import eabnp.eflow.server.impl.hb.EFlowHBUtil;
import eabnp.eflow.server.impl.hb.cache.EFlowCache;
import eabnp.eflow.server.impl.hb.cache.FlowInfoCache;
import eabnp.eflow.server.impl.hb.flowengine.misc.CurProcessState;
import eabnp.eflow.server.impl.hb.flowengine.misc.SendCache;
import eabnp.eflow.server.impl.hb.flowengine.misc.SendCacheList;
import eabnp.eflow.server.impl.hb.flowengine.misc.UserAndNoneUserList;
import eabnp.eflow.server.impl.hb.orm.HP_Comment;
import eabnp.eflow.server.impl.hb.orm.HP_Process;
import eabnp.eflow.server.impl.hb.orm.HP_Task;
import eabnp.eflow.server.impl.hb.orm.HP_Thread;
import eabnp.eflow.session.ESession;
import eabnp.eflow.tag.EFlowTagType;
import eabnp.eflow.tag.EFlowTagUtil;
import eabnp.etag.ETagUtil;
import eabnp.service.elog.ILogger;
import eabnp.service.hbcenter.HBSessionWrapper;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.hibernate.Query;
import org.hibernate.Session;

public class EFlowEngineHB_Send
{
  private static IResult batchSend(HBSessionWrapper sw, ESession es, List processIdList, String stepCode, String actName, String sendStr)
  {
    Session session = sw.getSession();
    UserCtrlInfo theUser = EFlowEngineHB_Basic.getTheUser(es, null);

    IResult r = getBatchSendTaskList(session, theUser, 
      processIdList, stepCode);
    if (r.isFailure()) return r;
    List taskList = (List)r.getResultObject();

    Iterator it = taskList.iterator();
    while (it.hasNext()) {
      HP_Task task = (HP_Task)it.next();
      CurProcessState curState = new CurProcessState(session, 
        task.getProcessId(), task);
      r = selSend(sw, es, theUser, curState, sendStr);
      if (r.isFailure()) {
        sw.setNeedRollBack();
        return r;
      }

      ActResultListCtrl arlCtrl = (ActResultListCtrl)r.getResultObject();
      r = EFlowEngineHB_Basic.opereateActResultBatchMode(sw, es, arlCtrl, 
        theUser, curState.getProcess().getAppData());
      if (r.isFailure()) {
        sw.setNeedRollBack();
        return r;
      }
    }

    return r;
  }

  public static IResult batchSend(ESession es, String processIdList, String stepCode, String actName, String sendStr)
  {
    String errMsg = "批量发送失败";

    List processList = StringUtil.splitToList(processIdList, 
      ";");
    if (MiscUtil.isNullOrEmptyCollection(processList)) {
      return GResult.newFailureResult("没有指定流程过程ID列表")
        .addErrMsgToIResult(errMsg);
    }
    if (StringUtil.isNullOrEmptyStr(stepCode)) {
      return GResult.newFailureResult("没有指定批量发送环节代码")
        .addErrMsgToIResult(errMsg);
    }
    if (StringUtil.isNullOrEmptyStr(actName)) {
      return GResult.newFailureResult("没有指定批量发送操作名称")
        .addErrMsgToIResult(errMsg);
    }
    GResult gr = EFlowHBUtil.openHBSession();
    if (gr.isFailure()) return gr.addErrMsgPreStr(errMsg);

    Session session = (Session)gr.getResultObject();
    HBSessionWrapper sw = new HBSessionWrapper(session, 
      EFlow.getInstance().getMyLogger());

    IResult r = null;
    try {
      r = batchSend(sw, es, processList, stepCode, actName, 
        sendStr);
    } catch (Exception ex) {
      r = gr.resetFailureResult("数据库操作失败", ex).addErrMsgToIResult(errMsg);
    }
    sw.close();
    if (r.isFailure()) {
      r.addErrMsgToIResult(errMsg);
      return r;
    }

    return SimpleResult.SUCCESS;
  }

  private static IResult getBatchSendTaskList(Session session, UserCtrlInfo theUser, List processIdList, String stepCode)
  {
    StringBuffer sb = new StringBuffer(200);
    sb.append("from ").append(HP_Task.class.getName()).append(" as task");
    sb.append(" where task.stateInt=").append(TaskState.DOING.ordinal);
    sb.append(" and task.curStepCode=:stepCode");
    sb.append(" and task.userUniqueName='").append(
      theUser.getUserInfo().getUniqueName()).append("'");
    sb.append(" and task.processId in(");
    MiscUtil.implodeCollectionEx(sb, processIdList, "'", "'", ",");
    sb.append(")");
    Query query = session.createQuery(sb.toString());
    query.setString("stepCode", stepCode);
    List taskList = query.list();

    if (processIdList.size() != taskList.size()) {
      return SGResult.newFailureResult("没有通过一致性检查");
    }

    return GResult.newSuccessResult(taskList);
  }

  private static IResult getBatchSendCtrl(HBSessionWrapper sw, ESession es, List processIdList, String stepCode, String actNameList, String theOUByApp, String theUserByApp)
  {
    Session session = sw.getSession();
    UserCtrlInfo theUser = EFlowEngineHB_Basic.getTheUser(es, null);

    IResult r = getBatchSendTaskList(session, theUser, 
      processIdList, stepCode);
    if (r.isFailure()) return r;

    List taskList = (List)r.getResultObject();
    HP_Task task = (HP_Task)taskList.get(0);
    HP_Thread thread = task.getThread();

    String flowUN = thread.getFlowUN();
    int flowVersion = thread.getFlowVersion();
    FlowInfoCache fCache = EFlowCache.getFlowCache(flowUN);
    if (fCache == null) return GResult.newFailureResult("没有找到『" + flowUN + "』");
    XFlow xFlow = fCache.getFlowDefine(flowVersion);
    XStep xStep = xFlow.getStepByCode(stepCode);
    if (xStep == null) {
      return GResult.newFailureResult("没有找到环节『" + stepCode + "』");
    }
    List actList = xStep.getActList();
    String[] sa = StringUtil.split(actNameList, ";");
    StringBuffer actIdSB = new StringBuffer();
    boolean emptySB = true;
    int n = sa.length;
    for (int i = 0; i < n; i++) {
      Iterator it = MiscUtil.getIterator(actList);
      while (it.hasNext()) {
        XAct a = (XAct)it.next();
        if ((a.getType() == ActType.SEND) && (actNameList.equals(a.getName(null)))) {
          if (emptySB)
            emptySB = false;
          else
            actIdSB.append(";");
          actIdSB.append(a.getId());
          break;
        }
      }
    }
    String actId = actIdSB.toString();
    if (StringUtil.isNullOrEmptyStr(actId)) {
      return GResult.newFailureResult("没有找到操作『" + actNameList + "』");
    }
    return getSendListCtrl(session, theUser, flowUN, xFlow, 
      xStep, task, actId, theOUByApp, theUserByApp);
  }

  public static IResult getBatchSendCtrl(ESession es, String processIdList, String stepCode, String actName, String theOUByApp, String theUserByApp)
  {
    String errMsg = "获取批量发送控制信息失败";

    List processList = StringUtil.splitToList(processIdList, 
      ";");
    if (MiscUtil.isNullOrEmptyCollection(processList)) {
      return GResult.newFailureResult("没有指定流程过程ID列表")
        .addErrMsgToIResult(errMsg);
    }
    if (StringUtil.isNullOrEmptyStr(stepCode)) {
      return GResult.newFailureResult("没有指定批量发送环节代码")
        .addErrMsgToIResult(errMsg);
    }
    if (StringUtil.isNullOrEmptyStr(actName)) {
      return GResult.newFailureResult("没有指定批量发送操作名称")
        .addErrMsgToIResult(errMsg);
    }
    GResult gr = EFlowHBUtil.openHBSession();
    if (gr.isFailure()) return gr.addErrMsgPreStr(errMsg);

    Session session = (Session)gr.getResultObject();
    HBSessionWrapper sw = new HBSessionWrapper(session, 
      EFlow.getInstance().getMyLogger());

    IResult r = null;
    try {
      r = getBatchSendCtrl(sw, es, processList, stepCode, 
        actName, theOUByApp, theUserByApp);
    } catch (Exception ex) {
      r = gr.resetFailureResult("数据库操作失败", ex).addErrMsgToIResult(errMsg);
    }
    sw.close();
    if (r.isFailure()) {
      r.addErrMsgToIResult(errMsg);
      return r;
    }

    return r;
  }

  public static IResult getSendCtrlInfo(ESession es, String processId, String taskId, String actId, String theOUByApp, String theUserByApp, String appData)
  {
    String errMsg = "获取发送控制信息失败";

    UserCtrlInfo theUser = EFlowEngineHB_Basic.getTheUser(es, processId);
    if (theUser == null) {
      return SGResult.newFailureResult("获取被代表的用户失败").addErrMsgPreStr(errMsg);
    }
    processId = EFlowEngineHB_Basic.getProcessId(processId);

    GResult gr = EFlowHBUtil.openHBSession();
    if (gr.isFailure()) return gr.addErrMsgPreStr(errMsg);

    Session session = (Session)gr.getResultObject();
    HBSessionWrapper sw = new HBSessionWrapper(session, 
      EFlow.getInstance().getMyLogger());

    IResult r = null;
    try {
      r = getSendListCtrl(sw, theUser, processId, taskId, actId, theOUByApp, 
        theUserByApp);
    } catch (Exception ex) {
      r = gr.resetFailureResult("数据库操作失败", ex);
    }
    sw.close();
    if (r.isFailure()) {
      r.addErrMsgToIResult(errMsg);
      return r;
    }

    SelSendListCtrl sc = (SelSendListCtrl)r.getResultObject();
    FormulaArray formulas = sc.genFormulaArray();
    if (!formulas.isEmpty()) {
      SGResult sr = null;
      try {
        sr = EFlowApiCall.validateFormula(es, 
          theUser.getUserInfo().getUniqueName(), sc.getFlowUN(), processId, formulas, appData);
      } catch (Exception ex) {
        return GResult.newFailureResult("验证公式失败", ex);
      }

      formulas = (FormulaArray)sr.getResultObject();
      sc.handleFormulaResult(formulas);
    }

    return r;
  }

  private static IResult getAutoSendConfirm(HBSessionWrapper sw, ESession es, UserCtrlInfo theUser, String processId, String taskId, String actId, String theOUByApp, String theUserByApp)
  {
    Session session = sw.getSession();

    CurProcessState curState = new CurProcessState(session, processId, taskId);

    HP_Process process = curState.getProcess();
    HP_Thread thread = curState.getCurThread();
    HP_Task task = curState.getCurTask();

    String flowUN = task.getThread().getFlowUN();
    String appUN = ETagUtil.getParentStr(flowUN);

    AppInfo appInfo = curState.getAppInfo();
    if (appInfo == null) {
      return SGResult.newFailureResult("无法在系统缓存中找到『" + appUN + "』");
    }
    FlowInfoCache fCache = EFlowCache.getFlowCache(flowUN);
    if (fCache == null) {
      return SGResult.newFailureResult("无法找到『" + flowUN + "』定义");
    }
    XFlow xFlow = fCache
      .getFlowDefine(curState.getCurThread().getFlowVersion());
    XAct xAct = xFlow.getActById(actId);
    if (xAct == null) return SGResult.newFailureResult("无法根据操作ID找到操作");
    if (xAct.getType() != ActType.SEND)
      return SGResult.newFailureResult("操作ID对应的操作类型错误");
    ActInfo actInfo = xAct.getActInfoFromCache();
    if (actInfo == null)
      return 
        SGResult.newFailureResult("无法找到操作『" + xAct.getUniqueName() + "』定义");
    XSend xSend = xAct.getSend();
    XReceiverScope xRS = xSend.getReceiverScope();
    if (xRS == null) return SGResult.newFailureResult("没有定义发送接收人");

    String msg = xSend.getPreMsg();
    ConfirmCtrl cc = new ConfirmCtrl();
    if (StringUtil.isNotNullEmptyStr(msg)) {
      if (EFlowConst.hasMsgPara(msg)) {
        XUserScope xUS = xRS.getUserScope();
        UserAndNoneUserList unuList = 
          EFlowEngineHB_Basic.getUserAndNoneUserList(session, xUS, theUser, process, thread, 
          task, theOUByApp, theUserByApp);
        String str = EFlowEngineHB_Basic.genMsgByPatternAndUserNoneUserList(
          msg, unuList, appInfo.getDepartmentLevel());
        if (!StringUtil.isContains(str, "是否确定"))
          str = str + "，是否确定？";
        cc.setConfirmStr(str);
        return SGResult.newSuccessResult(cc);
      }
      if (!StringUtil.isContains(msg, "是否确定"))
        msg = msg + "，是否确定？";
      return SGResult.newSuccessResult(cc.setConfirmStr(msg));
    }

    return SGResult.newSuccessResult(cc);
  }

  public static IResult getAutoSendConfirm(ESession es, String processId, String taskId, String actId, String theOUByApp, String theUserByApp)
  {
    UserCtrlInfo theUser = EFlowEngineHB_Basic.getTheUser(es, processId);
    if (theUser == null) {
      return SGResult.newFailureResult("获取被代表的用户失败").addErrMsgPreStr(
        "获取自动发送确认信息失败");
    }
    processId = EFlowEngineHB_Basic.getProcessId(processId);

    GResult gr = EFlowHBUtil.openHBSession();
    if (gr.isFailure()) return gr.addErrMsgPreStr("获取自动发送确认信息失败");

    Session session = (Session)gr.getResultObject();
    HBSessionWrapper sw = new HBSessionWrapper(session, 
      EFlow.getInstance().getMyLogger());

    IResult r = null;
    try {
      r = getAutoSendConfirm(sw, es, theUser, processId, taskId, actId, 
        theOUByApp, theUserByApp);
    } catch (Exception ex) {
      r.addErrMsgToIResult("获取自动发送确认信息失败");
    }

    sw.close();
    return r;
  }

  private static IResult getSendListCtrl(Session session, UserCtrlInfo theUser, String flowUN, XFlow xFlow, XStep xStep, HP_Task task, String actId, String theOUByApp, String theUserByApp)
  {
    ILogger logger = EFlow.getInstance().getMyLogger();

    SelSendListCtrl slCtrl = new SelSendListCtrl();
    slCtrl.setSysUN(EFlowTagUtil.getSysUNFromName(flowUN));
    slCtrl.setFlowUN(flowUN);
    if (xStep.getSplit() != null) {
      slCtrl.getSplitList().addAll(xStep.getSplit().toSplitCtrlList());
    }
    UserInfo ui = theUser.getUserInfo();
    slCtrl.setUserUN(ui.getUniqueName());
    slCtrl.setUserName(ui.getName());
    slCtrl.setUserParentUN(theUser.getOrgOrOUUN());
    slCtrl.setUserParentFN(ui.getParentFN());

    boolean excludeCurEditor = false;
    String[] actArray = StringUtil.split(actId, ";");
    int n = ArrayUtil.getArraySize(actArray);
    for (int i = 0; i < n; i++) {
      String id = actArray[i];
      XAct xAct = xFlow.getActById(id);
      if (xAct == null) {
        logger.logErr("在『" + flowUN + "』的流程定义中，没有找到操作『" + id + "』");
      }
      else {
        ActInfo actInfo = xAct.getActInfoFromCache();
        if (actInfo == null) {
          logger.logErr("在缓存中没有找到操作『" + xAct.getUniqueName() + "』");
        }
        else
        {
          SelSendCtrl selSendCtrl = xAct.toSendCtrl(actInfo);
          if (selSendCtrl.isSpecialGroup()) {
            String groupUN = selSendCtrl.getGroupOrUserList().get(0).toString();
            selSendCtrl.getGroupOrUserList().clear();
            EFlowEngineHB_Basic.addSpecialGroupUserToList(session, 
              task.getProcess(), task.getThread(), task, 
              selSendCtrl.getGroupOrUserList(), groupUN, theUserByApp);
          }

          AppInfo appInfo = EFlowEngineHB_Basic.getAppInfoByFlowUN(task.getThread()
            .getFlowUN());
          List list = selSendCtrl.getOrgOUList();
          List rList = new ArrayList();
          Iterator it = list.iterator();
          boolean hasSpecialOU = false;
          while (it.hasNext()) {
            String oUN = it.next().toString();
            if (EFlowConst.isSpecialGroupOrOU(oUN)) {
              hasSpecialOU = true;
              EFlowEngineHB_Basic.addSpecialOUToList(session, oUN, rList, 
                task.getProcess(), task.getThread(), task, 
                appInfo.getDepartmentLevel(), theOUByApp);
            } else {
              rList.add(oUN);
            }
          }
          if (hasSpecialOU) {
            MiscUtil.uniqueList(rList);
            list.clear();
            list.addAll(rList);
          }

          if ((!excludeCurEditor) && (selSendCtrl.getExcludeCurEditor() != null) && 
            (selSendCtrl.getExcludeCurEditor() != OrgOUUserLevel.NONE)) {
            excludeCurEditor = true;
          }

          slCtrl.addSendCtrl(selSendCtrl);
        }
      }
    }
    if (excludeCurEditor)
    {
      Set set = task.getProcess().getUndoneTaskSet();
      Iterator it = set.iterator();
      while (it.hasNext()) {
        HP_Task t = (HP_Task)it.next();
        if (!t.getUserUniqueName().equals(theUser.getUserInfo().getUniqueName())) {
          slCtrl.addCurEditor(t.toUserResult());
        }
      }
    }
    return SGResult.newSuccessResult(slCtrl);
  }

  private static IResult getSendListCtrl(HBSessionWrapper sw, UserCtrlInfo theUser, String processId, String taskId, String actId, String theOUByApp, String theUserByApp)
  {
    Session session = sw.getSession();

    HP_Task task = null;
    String flowUN = null;
    int flowVersion = 1;
    task = (HP_Task)session.get(HP_Task.class.getName(), taskId);
    if (task != null) {
      flowUN = task.getThread().getFlowUN();
      flowVersion = task.getThread().getFlowVersion();
    } else {
      return SGResult.newFailureResult("错误的任务ID");
    }

    FlowInfoCache fCache = EFlowCache.getFlowCache(flowUN);
    if (fCache == null) return GResult.newFailureResult("没有找到『" + flowUN + "』");
    XFlow xFlow = fCache.getFlowDefine(flowVersion);
    XStep xStep = xFlow.getStepByCode(task.getCurStepCode());

    return getSendListCtrl(session, theUser, flowUN, xFlow, 
      xStep, task, actId, theOUByApp, theUserByApp);
  }

  private static IResult autoSend(HBSessionWrapper sw, ESession es, UserCtrlInfo theUser, String processId, String taskId, String actId, String theOUByApp, String theUserByApp)
  {
    Session session = sw.getSession();

    CurProcessState curState = new CurProcessState(session, processId, taskId);

    HP_Process process = curState.getProcess();
    HP_Thread thread = curState.getCurThread();
    HP_Task task = curState.getCurTask();
    if ((task == null) || (task.getState() != TaskState.DOING)) {
      return SGResult.newFailureResult("3003", 
        "被收回或已被他人完成");
    }

    String flowUN = task.getThread().getFlowUN();
    String appUN = ETagUtil.getParentStr(flowUN);

    AppInfo appInfo = EFlowCache.getAppInfo(appUN);
    if (appInfo == null) {
      return SGResult.newFailureResult("无法在系统缓存中找到『" + appUN + "』");
    }
    FlowInfoCache fCache = EFlowCache.getFlowCache(flowUN);
    if (fCache == null) {
      return SGResult.newFailureResult("无法找到『" + flowUN + "』定义");
    }
    XFlow xFlow = fCache.getFlowDefine(thread.getFlowVersion());
    XAct xAct = xFlow.getActById(actId);
    ActInfo actInfo = xAct.getActInfoFromCache();
    if (actInfo == null) {
      return 
        SGResult.newFailureResult("无法找到操作『" + xAct.getUniqueName() + "』定义");
    }
    if (xAct == null) return SGResult.newFailureResult("无法根据操作ID找到操作");
    if (xAct.getType() != ActType.SEND) {
      return SGResult.newFailureResult("操作ID对应的操作类型错误");
    }
    XSend xSend = xAct.getSend();
    XReceiverScope xRS = xSend.getReceiverScope();
    if (xRS == null) return SGResult.newFailureResult("没有定义发送接收人");
    XUserScope xUS = xRS.getUserScope();
    if ((xUS == null) || (xUS.getScope() == null)) {
      return SGResult.newFailureResult("没有定义发送接收人");
    }
    UserAndNoneUserList unuList = EFlowEngineHB_Basic.getUserAndNoneUserList(
      session, xUS, theUser, process, thread, task, theOUByApp, theUserByApp);
    if (unuList == null) return SGResult.newFailureResult("没有找到合适的接收人");

    ActResultListCtrl arlCtrl = EFlowEngineHB_Basic.newActResultListCtrl(es, 
      theUser, process);

    Set commentSet = task.getCommentSet();
    if (commentSet.size() > 0) {
      HP_Comment comment = (HP_Comment)commentSet.iterator().next();
      arlCtrl.setCurComment(comment.getCommentContent(), comment.getSign(), 
        comment.getFillInTime());
    }

    Date now = DateTimeUtil.getNow();
    if (!sw.beginTransaction()) return SGResult.newFailureResult("开始数据库事务失败");
    IResult r = EFlowEngineHB_Basic.actAction(arlCtrl, sw, es, theUser, 
      curState, actId, actInfo, unuList.getUserList(), 
      unuList.getNoneUserList(), null, now);
    if (r.isFailure()) {
      sw.setNeedRollBack(true);
      return r;
    }

    return SGResult.newSuccessResult(arlCtrl);
  }

  public static IResult autoSend(ESession es, String processId, String taskId, String actId, String theOUByApp, String theUserByApp, String appData)
  {
    String errMsg = "自动发送操作失败";

    UserCtrlInfo theUser = EFlowEngineHB_Basic.getTheUser(es, processId);
    if (theUser == null) {
      return SGResult.newFailureResult("获取被代表的用户失败");
    }
    processId = EFlowEngineHB_Basic.getProcessId(processId);

    GResult gr = EFlowHBUtil.openHBSession();
    if (gr.isFailure()) return gr.addErrMsgPreStr(errMsg);

    Session session = (Session)gr.getResultObject();
    HBSessionWrapper sw = new HBSessionWrapper(session, 
      EFlow.getInstance().getMyLogger());

    IResult r = null;
    try {
      r = autoSend(sw, es, theUser, processId, taskId, actId, theOUByApp, 
        theUserByApp);
    } catch (Exception ex) {
      r = gr.resetFailureResult(errMsg, ex);
    }
    if (r.isFailure()) {
      sw.rollBackAndClose();
      return r.addErrMsgToIResult(errMsg);
    }

    ActResultListCtrl arlCtrl = (ActResultListCtrl)r.getResultObject();
    r = 
      EFlowEngineHB_Basic.opereateActResult(sw, es, arlCtrl, theUser, appData);
    if (r.isFailure()) r.addErrMsgToIResult(errMsg);
    return r;
  }

  private static IResult selSend(HBSessionWrapper sw, ESession es, UserCtrlInfo theUser, CurProcessState curState, SendCacheList srList)
  {
    if (!sw.beginTransaction()) return SGResult.newFailureResult("开始数据库事务失败");

    Iterator it = srList.getSendCacheList().iterator();
    ActResultListCtrl arlCtrl = EFlowEngineHB_Basic.newActResultListCtrl(es, 
      theUser, curState.getProcess());

    Set commentSet = curState.getCurTask().getCommentSet();
    if (commentSet.size() > 0) {
      HP_Comment comment = (HP_Comment)commentSet.iterator().next();
      arlCtrl.setCurComment(comment.getCommentContent(), comment.getSign(), 
        comment.getFillInTime());
    }

    Date now = DateTimeUtil.getNow();
    while (it.hasNext()) {
      SendCache sc = (SendCache)it.next();
      IResult r = EFlowEngineHB_Basic.actAction(arlCtrl, sw, es, theUser, 
        curState, sc.getActId(), null, sc.getUserResultList(), 
        sc.getNoneUserList(), sc.getParameters(), now);
      if (r.isFailure()) {
        sw.setNeedRollBack(true);
        return r;
      }
    }

    return SGResult.newSuccessResult(arlCtrl);
  }

  private static IResult selSend(HBSessionWrapper sw, ESession es, UserCtrlInfo theUser, CurProcessState curState, String sendStr)
  {
    if (curState.isNullTask()) return SGResult.newFailureResult("空的任务");

    String str = StringUtil.getXMLNodeValue(sendStr, "SendResult");
    String[] actIdArray = StringUtil.split(str, ";");
    int n = ArrayUtil.getArraySize(actIdArray);
    if (n == 0) return SGResult.newFailureResult("空的发送操作ID");

    SendCacheList scList = new SendCacheList();
    scList.setProcessId(curState.getCurTask().getProcessId());
    scList.setTaskId(curState.getCurTask().getId());

    for (int i = 0; i < n; i++) {
      SendCache sendCache = new SendCache();

      String actId = actIdArray[i];
      XAct xAct = curState.getFlowCache().getFlowDefine(
        curState.getCurThread().getFlowVersion()).getActById(actId);
      if (xAct == null)
        return SGResult.newFailureResult("在流程定义中没有找到操作『" + actId + "』");
      if (xAct.getType() != ActType.SEND) {
        return SGResult.newFailureResult("在流程定义中的操作『" + actId + "』类型错误");
      }
      String actResult = StringUtil.getXMLNodeValue(sendStr, actId);
      str = StringUtil.getXMLNodeValue(actResult, "U");
      List userUNList = StringUtil.splitToList(str, 
        ";");
      List noneUserList = 
        EFlowEngineHB_Basic.genNoneUserListByUserUNList(userUNList);

      List urList = null;
      if (userUNList.size() > 0) {
        StringBuffer sb = new StringBuffer();

        sb.append("select ");
        EFlowEngineHB_Basic.appendHQLNewUserResult(sb, "user");
        sb.append(" from ");
        sb.append(EFlowHBUtil.getClassName(EFlowTagType.USER));
        sb.append(" as user where user.uniqueName in (");
        MiscUtil.implodeCollectionEx(sb, userUNList, "'", "'", ",");
        sb.append(")");

        Query q = sw.getSession().createQuery(sb.toString());
        urList = q.list();

        Iterator it = urList.iterator();
        while (it.hasNext()) {
          UserResult ur = (UserResult)it.next();
          ur.setSequenceNum(userUNList.indexOf(ur.getUserUniqueName()));
        }
        Collections.sort(urList, ComparatorBySeqNum.getComparator());
      }

      sendCache.setActId(actId);
      sendCache.setUserResultList(urList);
      sendCache.setNoneUserList(noneUserList);
      sendCache.setPreMsg(xAct.getSend().getPreMsg());
      sendCache.setPostMsg(xAct.getSend().getPostMsg());

      scList.getSendCacheList().add(sendCache);
    }

    return selSend(sw, es, theUser, curState, scList);
  }

  public static IResult selSend(ESession es, String processId, String taskId, String sendStr, String appData)
  {
    String errMsg = "选人发送操作失败";

    if (StringUtil.isNullOrEmptyStr(sendStr)) {
      return SGResult.newFailureResult("空的发送选人结果");
    }
    UserCtrlInfo theUser = EFlowEngineHB_Basic.getTheUser(es, processId);
    if (theUser == null) {
      return SGResult.newFailureResult("获取被代表的用户失败");
    }
    processId = EFlowEngineHB_Basic.getProcessId(processId);

    GResult gr = EFlowHBUtil.openHBSession();
    if (gr.isFailure()) return gr.addErrMsgPreStr(errMsg);

    Session session = (Session)gr.getResultObject();
    HBSessionWrapper sw = new HBSessionWrapper(session, 
      EFlow.getInstance().getMyLogger());

    IResult r = null;
    try {
      CurProcessState curState = new CurProcessState(session, processId, taskId);
      if ((curState.getCurTask() == null) || 
        (curState.getCurTask().getState() != TaskState.DOING))
        r = SGResult.newFailureResult("3003", 
          "被收回或已被他人完成");
      else
        r = selSend(sw, es, theUser, curState, sendStr);
    }
    catch (Exception ex) {
      r = gr.resetFailureResult(errMsg, ex);
    }

    if (r.isFailure()) {
      sw.close();
      return r.addErrMsgToIResult(errMsg);
    }

    ActResultListCtrl arlCtrl = (ActResultListCtrl)r.getResultObject();
    r = 
      EFlowEngineHB_Basic.opereateActResult(sw, es, arlCtrl, theUser, appData);
    if (r.isFailure()) r.addErrMsgToIResult(errMsg);
    return r;
  }
}